package com.itheima.web.manager;

import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.domain.db.*;
import com.itheima.service.db.AdminService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.service.mongo.VideoService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.MovementVo;
import com.itheima.vo.PageBeanVo;
import com.itheima.vo.VideoVo;
import com.itheima.web.exception.BusinessException;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.*;

/**
 * @author zsk
 * @create 2022-03-24-15:48
 */
@Component
public class AdminManager {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private AdminService adminService;

    @DubboReference
    private UserInfoService userInfoService;

    @DubboReference
    private MovementService movementService;

    @DubboReference
    private CommentService commentService;

    @DubboReference
    private VideoService videoService;


    //登录时获取验证码图片
    public LineCaptcha verification(String uuid) {

        //使用hutool制作验证码
        LineCaptcha lineCaptcha = new LineCaptcha(200,100);

        //验证码存储到Redis中,失效5分钟
        stringRedisTemplate.opsForValue().set(ConstantUtil.ADMIN_CODE +uuid,lineCaptcha.getCode(),
                Duration.ofMinutes(5));

        //返回验证码
        return lineCaptcha;
    }

    //登录验证
    public ResponseEntity login(String username, String password,String verificationCode, String uuid) {

        //根据uuid查询redis验证码
        String code = stringRedisTemplate.opsForValue().get(ConstantUtil.ADMIN_CODE + uuid);

        //比对验证码
        if (!StrUtil.equals(verificationCode,code)){
            throw new BusinessException("验证码不正确");
        }

        //根据用户名和密码查询数据库
        Admin admin = adminService.findAdmin(username, password);
        if (admin == null){
            throw new BusinessException("用户名密码不正确");
        }

        admin.setPassword(null);//不希望前端解析密码
        //登录成功，通过JWT制作token
        Map<String, Object> claims = BeanUtil.beanToMap(admin);
        String token = JwtUtil.createToken(claims);

        //Redis中存储token,时效1小时
        String json = JSON.toJSONString(admin);
        stringRedisTemplate.opsForValue().set(ConstantUtil.ADMIN_TOKEN + token,json,Duration.ofHours(1));

        //删除Redis中存储的验证码
        stringRedisTemplate.delete(ConstantUtil.ADMIN_CODE + uuid);

        //返回token
        Map map = new HashMap();
        map.put("token",token);
        return ResponseEntity.ok(map);
    }

    //校验token信息
    public Admin findAdminByToken(String token) {

        //前端携带token会加上Bearer token
        token = token.replace("Bearer ","");

        //根据token查询Redis信息
        String json = stringRedisTemplate.opsForValue().get(ConstantUtil.ADMIN_TOKEN + token);

        //判断
        if (StrUtil.isEmpty(json)){//如果为null
            return null;//设置为null
        }

        //将json转为admin对象
        Admin admin = JSON.parseObject(json, Admin.class);
        //Redis续期1小时
        stringRedisTemplate.opsForValue().set(ConstantUtil.ADMIN_TOKEN + token,json,Duration.ofHours(1));

        //返回admin
        return admin;
    }

    //用户退出
    public void logout(String token) {
        //删除Redis中的token信息
        token = token.replace("Bearer ","");
        stringRedisTemplate.delete(ConstantUtil.ADMIN_TOKEN + token);
    }

    //用户列表
    public ResponseEntity findUserInfoByPage(Integer pageNum, Integer pageSize) {

        //调用rpc查询
        PageBeanVo pageBeanVo = userInfoService.findUserInfoByPage(pageNum, pageSize);

        //返回分页对象
        return ResponseEntity.ok(pageBeanVo);

    }

    //用户详情列表
    public ResponseEntity users(Long userId) {

        //根据id查询用户详情
        UserInfo userInfo = userInfoService.findById(userId);

        //返回前端页面
        return ResponseEntity.ok(userInfo);

    }

    //查询用户动态详情
    public ResponseEntity messages(Long userId, Integer stateInt,Integer pageNum, Integer pageSize) {

        //调用rpc查询动态分页对象
        PageBeanVo pageBeanVo = movementService.findMovementByPage(userId, stateInt, pageNum, pageSize);

        List<MovementVo> voList = new ArrayList<>();
        //封装MovementVo对象
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        if (CollectionUtil.isNotEmpty(movementList)){
            for (Movement movement : movementList) {

                MovementVo vo = new MovementVo();
                //封装userInfo对象
                vo.setUserInfo(userInfoService.findById(movement.getUserId()));

                //后封装movement对象
                vo.setMovement(movement);
                //设置具体动态时间
                vo.setCreateDate(DateUtil.formatDateTime(new Date(movement.getCreated())));
                //添加到集合对象中
                voList.add(vo);
            }
        }

        //添加到分页对象中
        pageBeanVo.setItems(voList);

        //返回结果
        return ResponseEntity.ok(pageBeanVo);

    }

    //用户动态记录
    public ResponseEntity findMovementVoById(String publishId) {

        //调用rpc根据id查询动态
        Movement movement = movementService.findById(new ObjectId(publishId));

        //封装movementVo对象
        MovementVo vo = new MovementVo();
        //先封装userInfo信息
        vo.setUserInfo(userInfoService.findById(movement.getUserId()));

        //再封装movement信息
        vo.setMovement(movement);

        //封装发表动态的时间
        vo.setCreateDate(DateUtil.formatDateTime(new Date(movement.getCreated())));

        //返回前端
        return ResponseEntity.ok(vo);

    }

    //用户评论详情
    public ResponseEntity findCommentVoByPage( String publishId,Integer pageNum, Integer pageSize) {

        //调用rpc查询评论详情
        PageBeanVo pageBeanVo = commentService.findCommentByPage(
                new ObjectId(publishId), 2, pageNum, pageSize);//2是类型

        List<CommentVo> voList = new ArrayList<>();
        //封装CommentVo对象
        List<Comment> commentList = (List<Comment>) pageBeanVo.getItems();
        if (CollectionUtil.isNotEmpty(commentList)){
            for (Comment comment : commentList) {

                CommentVo vo = new CommentVo();
                //先封装userInfo
                UserInfo userInfo = userInfoService.findById(comment.getUserId());
                vo.setAvatar(userInfo.getAvatar());//评论人头像
                vo.setNickname(userInfo.getNickname());//评论人昵称

                vo.setId(comment.getId().toHexString());//评论id
                vo.setContent(comment.getContent());//评论内容
                vo.setCreateDate(DateUtil.formatDateTime(new Date(comment.getCreated())));

                //添加到集合
                voList.add(vo);
            }
        }
        //添加到分页对象
        pageBeanVo.setItems(voList);

        //返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    //用户视频详情
    public ResponseEntity findByUserVideos(Long userId, Integer pageNum, Integer pageSize) {

        //按照用户id查询分页对象
        PageBeanVo pageBeanVo = videoService.findByUserVideos(userId, pageNum, pageSize);

        List<VideoVo> voList = new ArrayList<>();
        //封装VideoVo对象
        List<Video> videoList = (List<Video>) pageBeanVo.getItems();

        if (CollectionUtil.isNotEmpty(videoList)){
            for (Video video : videoList) {

                VideoVo vo = new VideoVo();

                //先封装UserInfo
                vo.setUserInfo(userInfoService.findById(video.getUserId()));

                //后封装video
                vo.setVideo(video);

                //添加到集合对象中
                voList.add(vo);
            }
        }

        //添加集合到分页对象中
        pageBeanVo.setItems(voList);

        //返回分页对象
        return ResponseEntity.ok(pageBeanVo);

    }
}
